package stack;


import java.io.IOException;
import java.util.concurrent.Semaphore;
import java.util.logging.FileHandler;
import java.util.logging.Logger;


public class StackWorker implements Runnable {

	private Stack stack_;
	
	
	
	private Semaphore permits_;

	private Logger logger_;
	public static final int POP=0;
	public static final int PUSH=1;
	
	public static final double MIN_FACTOR = 0.1;
	public static final int ADAPT_INIT = 0;
	public static final double MAX_FACTOR = 1;
	public static final int MAX_COUNT = 2;


	

	private Cell cell_;
	private int id_;
	private int actions_num_;
	private int  op_;
	private WorkerStat data_;
	private long spin_;
	private double adaptFactor_;
	private int adaptCount_;
	
	WorkerInfo worker_info_;



	
	



	 


	public StackWorker(Stack stack, int id, int op, int actions, Semaphore permits) {

		stack_ = stack;
		id_ = id;
		op_ = op;
		actions_num_=actions;
		permits_=permits;
		data_ = new WorkerStat();
		spin_ = 1;
		adaptFactor_ = 1; 
		adaptCount_ = 0; 
	}
	
	public void init(){
	
		String loggerName = this.getClass().getName()+id_;
		logger_ = Logger.getLogger(loggerName);
		String logFile = "log\\worker"+id_;
		try {
			FileHandler handler = new FileHandler(logFile);
			Logger logger = Logger.getLogger(loggerName);
	        logger.addHandler(handler);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}


	@Override
	public void run() {
		for (int i = 0; i < actions_num_; i++) {
			cell_ = new Cell("ID worker "+ id_ + " entered " + i);
			worker_info_ = createInfo();
			stack_.stackOp(worker_info_);
			update();
		}
		permits_.release();
	}


	private WorkerInfo createInfo() {
		worker_info_ = new WorkerInfo();
		worker_info_.cell_=cell_;
		worker_info_.op_=op_;
		worker_info_.id_=id_;
		worker_info_.spin_=spin_;
		worker_info_.adaptFactor_=adaptFactor_;
		worker_info_.adaptCount_=adaptCount_;
		worker_info_.failure_=0;
		worker_info_.success_=0; 
		worker_info_.logger_=logger_;
		return worker_info_;
	}

	private void update() {
		//cell_=worker_info_.cell_;//TODO insert all to the returned cells, relevant only for popping workers. 
		adaptFactor_ = worker_info_.adaptFactor_;
		adaptCount_=worker_info_.adaptCount_;
		data_.failure_+=worker_info_.failure_;
		data_.success_+=worker_info_.success_;
	}
	
	
	public WorkerStat getStat(){
		return data_;
	}

	public class WorkerStat {


		int success_;
		int failure_;

		public int getSuccess(){
			return success_;
		}

		public int getFailure(){
			return failure_;
		}

	}

	
	
	class WorkerInfo{
		Cell cell_;
		int op_;
		int id_;
		long spin_;
		double adaptFactor_;
		int adaptCount_;
		int failure_;
		int success_;
		Logger logger_;
		
		
		void logPop(long time, String location) {
			logger_.info("in time " + time + " Worker " +id_ +" Pop \""+ cell_.data_+ "\" in " + location);
			
		}
		
		void logPush(long time, String location) {
			logger_.info("in time " + time + " Worker " +id_ +" Pushed \""+ cell_.data_+ "\" in " + location);
			
		}
		
		
		
	}





}
